﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace JESAI.DistributedLock
{
    /// <summary>
    /// 互斥同步原语，可用于协调对资源或关键代码区域的访问
    /// 跨流程或系统。锁的范围和功能取决于特定的实现
    /// </summary>
    public interface IDistributedLock
    {
        /// <summary>
        /// 唯一标识锁的名称
        /// </summary>
        string Name { get; }

        /// <summary>
        ///尝试同步获取锁。用法： 
        /// <code>
        ///     using (var handle = myLock.TryAcquire(...))
        ///     {
        ///         if (handle != null) { /* 我们获得锁！ */ }
        ///     }
        ///     //如果我们获取到锁，dispose就会解锁
        /// </code>
        /// </summary>
        /// <param name="timeout">等待放弃获取锁尝试的时间长度。默认为0。</param>
        /// <param name="cancellationToken">指定一个令牌，通过该令牌可以取消等待</param>
        /// <returns>An <see cref="IDistributedSynchronizationHandle"/>可用于在故障时释放锁或清零</returns>
        IDistributedSynchronizationHandle? TryAcquire(TimeSpan timeout = default, CancellationToken cancellationToken = default);

        /// <summary>
        /// 同步获取锁，如果尝试超时，则以<see cref="TimeoutException"/>失败。用法：
        /// <code>
        ///     using (myLock.Acquire(...))
        ///     {
        ///         /* 我们获得锁！ */
        ///     }
        ///     // dispose释放锁
        /// </code>
        /// </summary>
        /// <param name="timeout">在放弃收购尝试之前要等多久。默认为 <see cref="Timeout.InfiniteTimeSpan"/></param>
        /// <param name="cancellationToken">指定一个令牌，通过该令牌可以取消等待</param>
        /// <returns>An <see cref="IDistributedSynchronizationHandle"/>可用于释放锁</returns>
        IDistributedSynchronizationHandle Acquire(TimeSpan? timeout = null, CancellationToken cancellationToken = default);

        /// <summary>
        /// 尝试异步获取锁。用法: 
        /// <code>
        ///     await using (var handle = await myLock.TryAcquireAsync(...))
        ///     {
        ///         if (handle != null) { /* 我们获得锁！*/ }
        ///     }
        ///     // 如果我们获取到锁，dispose就会解锁
        /// </code>
        /// </summary>
        /// <param name="timeout">等待放弃获取锁尝试的时间长度。默认为0。</param>
        /// <param name="cancellationToken">指定一个令牌，通过该令牌可以取消等待</param>
        /// <returns>An <see cref="IDistributedSynchronizationHandle"/>可用于在故障时释放锁或清零</returns>
        ValueTask<IDistributedSynchronizationHandle?> TryAcquireAsync(TimeSpan timeout = default, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步获取锁，如果尝试超时，则以<see cref="TimeoutException"/>失败。用法：
        /// <code>
        ///     await using (await myLock.AcquireAsync(...))
        ///     {
        ///         /* 我们获得锁！*/
        ///     }
        ///     // dispose释放锁
        /// </code>
        /// </summary>
        /// <param name="timeout">在放弃收购尝试之前要等多久。默认为 <see cref="Timeout.InfiniteTimeSpan"/></param>
        /// <param name="cancellationToken">指定一个令牌，通过该令牌可以取消等待</param>
        /// <returns>An <see cref="IDistributedSynchronizationHandle"/>可用于解锁</returns>
        ValueTask<IDistributedSynchronizationHandle> AcquireAsync(TimeSpan? timeout = null, CancellationToken cancellationToken = default);
    }
}
